﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Crm.Sdk.Samples;
using CtefCrmImport.Common.Interfaces;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using CtefCrmImport.Common.Extensions;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Messages;

namespace CtefCrmImport.Common.Operations
{
    public class DeleteDonors
    {
        private const int DonorType = 100000001;
        private CommonOperations common;
        private ILogger logger;
        private ServerConnection.Configuration config;

        public DeleteDonors(ILogger logger, ServerConnection.Configuration config)
        {
            this.logger = logger;
            common = new CommonOperations(logger);
            this.config = config;
        }

        public void DeleteDuplicateDonors()
        {
            using (var serviceProxy = new OrganizationServiceProxy(config.OrganizationUri,
                                                                   config.HomeRealmUri,
                                                                   config.Credentials,
                                                                   config.DeviceCredentials))
            {
                // This statement is required to enable early-bound type support.
                serviceProxy.ServiceConfiguration.CurrentServiceEndpoint.Behaviors.Add(new ProxyTypesBehavior());

                IOrganizationService service = serviceProxy;
                common.CheckVersion(service);
                var contactMap = common.BuildFullNameContactMap(service);

                foreach (var c in contactMap.Keys)
                {
                    if (1 < contactMap[c].Count())
                    {
                        foreach (var cref in contactMap[c])
                        {
                            var contact = service.Retrieve("contact", cref.Id, new ColumnSet("customertypecode"));
                            var contactType = contact.GetAttributeValue<OptionSetValue>("customertypecode").Value;
                            if (contactType == DonorType && common.GetDonationsByDonorId(service, cref.Id).Count() == 0)
                            {
                                service.Delete("contact", cref.Id);
                                logger.Log("Deleted donor: {0}", c);
                                continue;   // will delete at most one record each time
                            }
                        }
                    }
                }
            }
        }

        public void DeleteDonorsByName(string firstName, string lastName)
        {
            var total = 0;
            using (var serviceProxy = new OrganizationServiceProxy(config.OrganizationUri,
                                                                   config.HomeRealmUri,
                                                                   config.Credentials,
                                                                   config.DeviceCredentials))
            {
                // This statement is required to enable early-bound type support.
                serviceProxy.ServiceConfiguration.CurrentServiceEndpoint.Behaviors.Add(new ProxyTypesBehavior());

                IOrganizationService service = serviceProxy;
                common.CheckVersion(service);

                firstName = firstName.ToKey(false);
                lastName = lastName.ToKey(false);

                using (var orgSvcContext = new OrganizationServiceContext(service))
                {
                    var contacts = orgSvcContext.CreateQuery("contact");
                    foreach (var c in contacts)
                    {
                        var fName = c.GetAttributeValue<string>("firstname").ToKey(false);
                        var lName = c.GetAttributeValue<string>("lastname").ToKey(false);

                        if (firstName.Equals(fName, StringComparison.OrdinalIgnoreCase) && lastName.Equals(lName, StringComparison.OrdinalIgnoreCase))
                        {
                            var id = c.GetAttributeValue<Guid?>("contactid");
                            if (!id.HasValue)
                            {
                                continue;
                            }

                            var count = common.GetDonationsByDonorId(service, id.Value).Count();
                            if (0 < count)
                            {
                                logger.Log("Contact id {0} has {1} donation(s). Will not delete Contact", id, count);
                            }
                            else
                            {
                                orgSvcContext.DeleteObject(c);
                                orgSvcContext.SaveChanges();
                                total++;
                                logger.Log("Deleted contact id {0}.", id.Value);
                            }                            
                        }
                    }
                }
            }

            logger.Log("Deleted {0} record(s).", total);
            logger.Flush();
        }
    }
}
